package cn.iocoder.yudao.module.aiposter.utils;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.aiposter.enums.ErrorCodeConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

public class CommonUtils {
    public static final String TMP_PATH = "/tmp/poster";

    public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f",
            "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
            "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z" };


    public static String generateTicket() {
        String ticket = UUID.randomUUID().toString();
        return ticket.replaceAll("-", "");
    }

    public static String generateShortUuid() {
        //调用Java提供的生成随机字符串的对象：32位，十六进制，中间包含-
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");

        for (int i = 0; i < 8; i++) {                       //分为8组
            String str = uuid.substring(i * 4, i * 4 + 4);  //每组4位
            int x = Integer.parseInt(str, 16);              //将4位str转化为int 16进制下的表示

            //用该16进制数取模62（十六进制表示为314（14即E）），结果作为索引取出字符
            shortBuffer.append(chars[x % 0x3E]);
        }
        return shortBuffer.toString();
    }

    /**
     * 为文件名添加后缀
     * @param originName 源文件
     * @return 增加uuid后缀的新文件名
     */
    public static String generateNewFileName(String originName){
        File file = new File(originName);
        String pureName = file.getName();
        // 文件名增加一个随机后缀
        int dotIndex = pureName.lastIndexOf('.');
        String nameWithoutExtension = (dotIndex == -1) ? pureName : pureName.substring(0, dotIndex);
        String extensionWithDot = (dotIndex == -1) ? pureName : pureName.substring(dotIndex);
        return nameWithoutExtension + "_" + generateShortUuid() + extensionWithDot;
    }

    /**
     * 保存base64文件为图片
     *
     * @param base64 图片base64
     * @param suffix 图片后缀
     * @param saveTmpPath 存储地址 不带文件名不带分隔符
     * @return 文件地址
     */
    public static String saveBase64(String base64, String suffix, String saveTmpPath){
        if (base64 == null) //图像数据为空
            return null;

        /**
         * 修复html显示的bsase64格式问题
         */
        if(base64.startsWith("data:")){
            base64 = base64.substring(base64.indexOf(",")+1);
        }

        //对字节数组字符串进行Base64解码并生成图片
        String tmpFilename = CommonUtils.generateShortUuid() + "." + suffix;
        BASE64Decoder decoder = new BASE64Decoder();
        String imgFilePath = saveTmpPath + File.separator + tmpFilename;//新生成的图片
        try(OutputStream out = new FileOutputStream(imgFilePath)) {
            //Base64解码
            byte[] b = decoder.decodeBuffer(base64);
            for(int i=0;i<b.length;++i)
            {
                if(b[i]<0)
                {//调整异常数据
                    b[i]+=256;
                }
            }
            File tmp = new File(saveTmpPath);
            if (!tmp.exists()) {
                tmp.mkdirs();
            }
            out.write(b);
            out.flush();
            return imgFilePath;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取inputstream为byte数据
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        try(ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            while((len = inputStream.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        }
    }

    public static String readInputStreamToString(InputStream inputStream) throws IOException {
        byte[] getData = readInputStream(inputStream);
        return new String(getData);
    }

    public static String readInputStreamToBase64(InputStream inputStream) throws IOException {
        byte[] data = readInputStream(inputStream);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    /**
     * 根据指定范围获取N个随机数
     * @param n 指定返回个数
     * @param start 开始位置 从0开始
     * @param end 结束位置 不包含结束位置
     * @return 不重复的n个数
     */
    public static List<Integer> generateRandomNumbers(int n, int start, int end) {
        if (n < 0 || start > end) {
            throw new IllegalArgumentException("Invalid input parameters.");
        }
        if(start == end){
            return new ArrayList<>();
        }
        Set<Integer> resultSet = new HashSet<>();
        if(n > end-start){
            for(int i = start; i<end; i++){
                resultSet.add(i);
            }
            return new ArrayList<>(resultSet);
        }
        Random random = new Random();

        while (resultSet.size() < n) {
            int randomNumber = random.nextInt(end - start) + start;
            resultSet.add(randomNumber);
        }
        return new ArrayList<>(resultSet);
    }

    public static String getImgBase64(MultipartFile multipartFile) throws IOException{
       return readInputStreamToBase64(multipartFile.getInputStream());
    }

    /**
     * 获取文件后缀
     * @param filePath
     * @return
     */
    public static String getFileSuffix(String filePath){
        return filePath.substring(filePath.lastIndexOf(".") + 1);
    }
    /**
     * 读取远程文件 获取base64信息
     *
     * @param remotePath 不包含bucket的url路径
     * @return base64信息 不包含data:base64文件头
     */
    public static String getImgBase64(String remotePath) {
        if (StringUtils.isEmpty(remotePath)) {
            return null;
        }
        InputStream inputStream = null;
        try {
            if (remotePath.startsWith("http")) {
                inputStream = getImgStreamWithUrl(remotePath);
            } else {
                throw new ServiceException(ErrorCodeConstants.POSTER_BASE_TRANSFORMER_ERROR);
            }
            if (inputStream != null) {
                return readInputStreamToBase64(inputStream);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 读取远程文件
     *
     * @param imgUrl http连接
     * @return 返回minio文件地址
     */
    private static InputStream getImgStreamWithUrl(String imgUrl) {
        if (null == imgUrl || !imgUrl.startsWith("http")) {
            return null;
        }
        HttpURLConnection httpUrl;
        try{
            URL url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();
            return httpUrl.getInputStream();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
